package org.facyt.vacas.daos.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.facyt.commons.util.StringUtils;
import org.facyt.vacas.daos.MateriaPrimaDAO;
import org.facyt.vacas.entities.login.Grupo;
import org.facyt.vacas.entities.vacas.Clasificacion;
import org.facyt.vacas.entities.vacas.Componente;
import org.facyt.vacas.entities.vacas.ComponenteValor;
import org.facyt.vacas.entities.vacas.MateriaPrima;
import org.facyt.vacas.entities.vacas.Unidad;
import org.facyt.vacas.util.ConstantesServices;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public class MateriaPrimaDAOImpl implements MateriaPrimaDAO {
 
	private static final Log logger = LogFactory.getLog(MateriaPrimaDAOImpl.class);
	
	@PersistenceContext
	private EntityManager entityManager;

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	public MateriaPrima getMateriaPrimaById(Integer id) throws Exception {
		MateriaPrima resultado = null;
		StringBuilder queryString = new StringBuilder();

		queryString.append("FROM MateriaPrima m where ");
		queryString.append("m.id = :codigo ");

		try {
			// se crea la cuery
			Query query = this.entityManager
					.createQuery(queryString.toString());

			query.setParameter("codigo", id);

			@SuppressWarnings("unchecked")
			List<MateriaPrima> lista = (List<MateriaPrima>) query
					.getResultList();

			if (!lista.isEmpty())
				resultado = lista.get(0);

			// resultado.setComposicion(this.getComposicionMateriaPrima(id));

		} catch (Exception e) {
			logger.error("",e);
			throw e;
			//return n/ull;
		}

		return resultado;
	}


	public List<MateriaPrima> getAllMateriaPrima(long idgrupodelusuario)
			throws Exception {

		List<MateriaPrima> lista = null;
		StringBuilder queryString = new StringBuilder();

		// Si el id del grupo que viene como parametro es Facyt, se deben
		// mostrar TODAS las mp. de la base
		//  buscar las materias primas del usuario 1 Facyt mas las del
		// usuarios idusuario.
		queryString.append("FROM MateriaPrima materiaprima ");
		if(idgrupodelusuario!=ConstantesServices.IDGRUPOFACYT)
		{
			queryString.append("where materiaprima.grupo.id = :id ");		
			queryString.append("or materiaprima.grupo.id = :idFacyt ");
		}

		try {
			// se crea la cuery
			Query query = this.entityManager
					.createQuery(queryString.toString());
			if(idgrupodelusuario!=ConstantesServices.IDGRUPOFACYT)
			{
				query.setParameter("id", idgrupodelusuario);
				query.setParameter("idFacyt", ConstantesServices.IDGRUPOFACYT);
			}

			lista = (List<MateriaPrima>) query.getResultList();

		} catch (Exception e) {
			logger.error("",e);
			return null;
		}

		return lista;
	}

	
	public ComponenteValor getComponenteFromComposicion(MateriaPrima mp,
			Componente componente) {

		// devuelve el la cantidad de aporte del componente que tiene la materia
		// prima
		
		BigDecimal resultado = null;
		
		ComponenteValor cv1 = new ComponenteValor();
		cv1.setComponente(componente);	
		
		StringBuilder queryString = new StringBuilder();

		queryString.append("select cantidad ");
		queryString.append("FROM m.composicion c where ");
		queryString.append(" fk_materia_prima = :mpid ");
		queryString.append(" and fk_componente = :cid ");

		try {
			// se crea la cuery
			Query query = this.entityManager
					.createQuery(queryString.toString());

			query.setParameter("mpid", mp.getId());
			query.setParameter("cid", componente.getId());

			@SuppressWarnings("unchecked")
			List<BigDecimal> lista = (List<BigDecimal>) query
					.getResultList();

			if (!lista.isEmpty())
				resultado = lista.get(0);

			// resultado.setComposicion(this.getComposicionMateriaPrima(id));

		} catch (Exception e) {
			// si la mp no aporta cantiadad de este componente, es decir que no esta
						// en su composicion
						// se devuelve un componente de cantidad 0.						
						cv1.setCantidad(BigDecimal.ZERO);
						return cv1;
		}	
		
		if(resultado != null)
		{			
			cv1.setCantidad(resultado);			
		}
		else{
			// si la mp no aporta cantiadad de este componente, es decir que no esta
			// en su composicion
			// se devuelve un componente de cantidad 0.
			cv1.setCantidad(BigDecimal.ZERO);	
		}

		return cv1;
	}

	
	public Float getCantidadCalcioFromComposicion(MateriaPrima mp) {
//
//		ComponenteValor cv = null;
//		StringBuilder queryString = new StringBuilder();
//		boolean noEncontrado = false;
//		List<ComponenteValor> listadoCV = mp.getComposicion();
//		for (int j = 0; j < listadoCV.size() && !noEncontrado; j++) {
//			if (((ComponenteValor) listadoCV.get(j)).getComponente()
//					.getDescripcion().equals(Constantes.Componentes.CALCIO)) {
//				noEncontrado = true;
//				return ((ComponenteValor) listadoCV.get(j)).getCantidad();
//			}
//		}

		// si la mp no aporta cantiadad de este componente, es decir que no esta
		// en su composicion
		// se devuelve un componente de cantidad 0.

		return new Float("0");
	}

	/**
	 * @return
	 */
	
	public int getCalculoColumnas(ArrayList<MateriaPrima> lista) {
	
		int cant = 0;
		Iterator mps = lista.iterator();
		int cantmp = 0;
		int cantComp = 0;
		while (mps.hasNext()) {
			MateriaPrima m = (MateriaPrima) mps.next();
			cantmp++;
			cantComp += m.getComposicion().size();
		}

		return cantComp;
	}

	
	public String toStringCodDescrip(MateriaPrima materiaPrima) {
		return materiaPrima.getId() + " - " + materiaPrima.getDescripcion();
	}

	
	public String getCostoXUnidadString(MateriaPrima materiaPrima, BigDecimal costo) {
		Unidad unidadId = materiaPrima.getUnidad();
		if (unidadId != null && materiaPrima.getCosto().compareTo(BigDecimal.ZERO) >= 0) {
			return StringUtils.getSimela2decimales(
			// new Double(materiaPrima .getCosto())
					costo.toString()) + " "
			// +
			// GestorPresentacion.getInstance().getValor("frame.gestionrestricciones.pesos")
					+ "$/" + unidadId.getDescripcion();
		} else
			return "";
	}

	@Transactional
	
	public MateriaPrima nuevaMateriaPrima(Grupo grupo, String descripcion,
			Unidad unidad, BigDecimal costo, Clasificacion clasificacion)
			throws Exception {
		MateriaPrima mp = new MateriaPrima();
		try {
			mp.setClasificacion(clasificacion);
			mp.setDescripcion(descripcion);
			mp.setGrupo(grupo);
			mp.setUnidad(unidad);
			mp.setCosto(costo);
			this.entityManager.persist(mp);
		} catch (Exception e) {
			logger.error("",e);
		}

		return mp;
	}

	
	public MateriaPrima setearCostoMP(MateriaPrima mp, BigDecimal costo) {
		MateriaPrima m = null;
		if (costo.compareTo(BigDecimal.ZERO) > 0) {
			try {
				m = entityManager.find(MateriaPrima.class, mp.getId());
				m.setCosto(costo);
				entityManager.merge(m);
			} catch (Exception e) {
				logger.error("",e);
				return mp;
			}
		}else{mp.setCosto(costo);
			return mp;}
		
		return m;
	}

	
	public MateriaPrima updateMateriaPrima(long idMP,Unidad unidad, BigDecimal costo,
			Clasificacion clasificacion, String nombre) throws Exception {
		MateriaPrima m = null;
		try{
			m = entityManager.find(MateriaPrima.class,idMP);
			m.setDescripcion(nombre);
			m.setClasificacion(clasificacion);
			m.setUnidad(unidad);
			m.setCosto(costo);
			entityManager.merge(m);
		} catch (Exception e) {
			logger.error("MP - usuario. ",e);
			
		}
		return m;
	}
	
	
	public MateriaPrima updateMateriaPrima(long idMP,Unidad unidad, BigDecimal costo,
			Clasificacion clasificacion) throws Exception {
		MateriaPrima m = null;
		try{
			m = entityManager.find(MateriaPrima.class,idMP);
			
			m.setClasificacion(clasificacion);
			m.setUnidad(unidad);
			m.setCosto(costo);
			entityManager.merge(m);
		} catch (Exception e) {
			logger.error("",e);
			
		}
		return m;
	}

	
	public ComponenteValor getComponenteFromComposicion(MateriaPrima mp,
			long componente) {
		// TODO: terminar, este metodo reemplaza a:
		// mp.getComponenteFromComposicion(componente);
		// devuelve el la cantidad de aporte del componente que tiene la materia
		// prima
		boolean noEncontrado = false;
		List<ComponenteValor> listadoCV = mp.getComposicion();
		for (int j = 0; j < listadoCV.size() && !noEncontrado; j++) {
			if (((ComponenteValor) listadoCV.get(j)).getComponente().getId() ==
					componente) {
				noEncontrado = true;
				return (ComponenteValor) listadoCV.get(j);
			}
		}

		// si la mp no aporta cantiadad de este componente, es decir que no esta
		// en su composicion se devuelve un componente de cantidad 0.
		ComponenteValor cv1 = new ComponenteValor();
		//cv1.setComponente(componente);
		cv1.setCantidad(BigDecimal.ZERO);

		return cv1;
	}

	
	public MateriaPrima getMateriaPrimaByNombre(String nombre)throws Exception {
		
		MateriaPrima resultado = null;
		StringBuilder queryString = new StringBuilder();

		queryString.append("FROM MateriaPrima m where ");
		queryString.append("upper(trim(m.descripcion)) = upper(trim(:nombre)) ");

		try {
			// se crea la cuery
			Query query = this.entityManager
					.createQuery(queryString.toString());

			query.setParameter("nombre", nombre);

			@SuppressWarnings("unchecked")
			List<MateriaPrima> lista = (List<MateriaPrima>) query
					.getResultList();

			if (!lista.isEmpty())
				resultado = lista.get(0);

			// resultado.setComposicion(this.getComposicionMateriaPrima(id));

		} catch (Exception e) {
			logger.error("",e);
			throw e;
			//return n/ull;
		}

		return resultado;
	}

	
	public MateriaPrima getMateriaPrimaByNombreYGrupo(String nombre, long grupo)
			throws Exception {
		MateriaPrima resultado = null;
		StringBuilder queryString = new StringBuilder();

		queryString.append("FROM MateriaPrima m where ");
		queryString.append("upper(trim(m.descripcion)) = upper(trim(:nombre)) and m.grupo.id = :grupo");

		try {
			// se crea la cuery
			Query query = this.entityManager
					.createQuery(queryString.toString());

			query.setParameter("nombre", nombre);
			query.setParameter("grupo", grupo);

			@SuppressWarnings("unchecked")
			List<MateriaPrima> lista = (List<MateriaPrima>) query
					.getResultList();

			if (!lista.isEmpty())
				resultado = lista.get(0);

			// resultado.setComposicion(this.getComposicionMateriaPrima(id));

		} catch (Exception e) {
			logger.error("",e);
			throw e;
			//return n/ull;
		}

		return resultado;
	}
		
	

}
